package org.mysfit.ctp4j.core.service.impl;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.mysfit.ctp4j.api.vo.BonsVO;
import org.mysfit.ctp4j.api.vo.QuoteVO;
import org.mysfit.ctp4j.api.vo.ReqVO;
import org.mysfit.ctp4j.core.service.FkDataService;
import org.mysfit.ctp4j.core.service.PloyService;
import org.mysfit.ctp4j.core.service.TradeService;
import org.mysfit.ctp4j.infra.entity.SkData;
import org.mysfit.ctp4j.infra.mapper.TradeMapper;
import org.mysfit.ctp4j.infra.pojo.CtpUser;
import org.mysfit.ctp4j.infra.utils.TradeConvertUtils;
import org.mysfit.ctp4j.infra.utils.TradeDataUtils;
import org.mysfit.ctp4j.infra.utils.TradeTimeUtils;
import org.mysfit.ctp4j.infra.utils.TradeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import ctp.thosttraderapi.CThostFtdcInputOrderActionField;
import ctp.thosttraderapi.CThostFtdcInputOrderField;
import ctp.thosttraderapi.CThostFtdcInvestorPositionField;
import ctp.thosttraderapi.CThostFtdcOrderField;
import ctp.thosttraderapi.CThostFtdcTradeField;
import ctp.thosttraderapi.CThostFtdcTraderApi;

/**
 * 
 * @author long.gf
 * @since 2022-12-06
 *
 */
@Service
public class TradeServiceImpl implements TradeService {
	
	@Autowired
	private PloyService polyService;
	
	@Autowired
	private TradeMapper tradeMapper;
	
	@Autowired
	private FkDataService fkService;
	
    private CThostFtdcTraderApi traderApi;
	
	private QuoteVO initQuoteVO(SkData sk,boolean isD,boolean isK) {
		QuoteVO q = new QuoteVO();
		q.setFid(sk.getFid());
		q.setFp(sk.getFp());
		q.setFtime(sk.getFtime());
		q.setKpFlag(isK ? TradeUtils.K_FLAG : TradeUtils.P_FLAG);
		if(isK) {
			q.setDirection(isD ? TradeUtils.D_FX : TradeUtils.K_FX);
			q.setCost(isD ? sk.getFp() + 3 : sk.getFp() - 3);
		}else {
			q.setDirection(isD ? TradeUtils.K_FX : TradeUtils.D_FX);
			q.setCost(isD ? sk.getFp() - 5 : sk.getFp() + 5);
		}
		q.setQty(1);
		return q;
	}
	
	@Override
	public void doCtpOrder(QuoteVO q) {
		CThostFtdcInputOrderField  order =  TradeConvertUtils.initOrderParams(q, CtpUser.getCurrUser());
		traderApi.ReqOrderInsert(order, order.getRequestID());
	}
	
	
	@Override
	public void doCtpCancleOrder(QuoteVO q) {
		CThostFtdcInputOrderActionField  order =  TradeConvertUtils.initOrderCancleParams(q, CtpUser.getCurrUser());
		traderApi.ReqOrderAction(order,order.getRequestID());
	}
	
	private void doSubmitOrder(SkData sk ,String polyDes,boolean isKC) {
		String polyNo = polyDes.split(",")[0];
		String dkFlag = polyDes.split(",")[1];
		QuoteVO q = initQuoteVO(sk,Integer.parseInt(dkFlag) > 0,isKC);
		q.setPloyNo(polyNo);
		q.setRequestId(TradeTimeUtils.getCurrReqId());
		ReqVO reqVo = TradeUtils.addQuoteReq(q);
		TradeDataUtils.getInstance(fkService, this).insertTradeReq(reqVo);
		this.doCtpOrder(q);
	}
	
	@Override
	public void doPolyOrder(SkData sk) {
		QuoteVO q = TradeUtils.checkQuoteId(sk.getFid(), sk.getFtime());
		if(null != q) {
			ReqVO reqVo = TradeUtils.addCancleReq(q);
			TradeDataUtils.getInstance(fkService, this).insertTradeReq(reqVo);
			this.doCtpCancleOrder(q);
		}else {
			String polyPcRes  = polyService.checkPolyPC(sk);
			String polyKcRes  = polyService.checkPolyKC(sk);
			if(StringUtils.isNotBlank(polyPcRes)) {
				this.doSubmitOrder(sk,polyPcRes,false);
			}
 			if(StringUtils.isNotBlank(polyKcRes)) {
 				this.doSubmitOrder(sk,polyKcRes,true);
 			}
		}
	}

	@Override
	public void onRtnOrder(CThostFtdcOrderField c) {
		if(StringUtils.isNotBlank(c.getOrderSysID())) {
			ReqVO reqVo = TradeUtils.addOrder(TradeConvertUtils.convertOrderRtn(c));
			TradeDataUtils.getInstance(fkService, this).insertTradeReq(reqVo);
		}
	}
	
	@Override
	public void onRtnTrade(CThostFtdcTradeField t) {
		if(StringUtils.isNotBlank(t.getTradeID())) {
			ReqVO reqVo =TradeUtils.addTrade(TradeConvertUtils.convertTradeRtn(t));
			TradeDataUtils.getInstance(fkService, this).insertTradeReq(reqVo);
			if(reqVo.getKpFlag() == 0) {
				TradeDataUtils.getInstance(fkService, this).insertTradeKC(reqVo);
			}else {
				TradeDataUtils.getInstance(fkService, this).insertTradePC(reqVo);
			}
		}
	}
	

	@Override
	public void onRtnBons(CThostFtdcInvestorPositionField t) {
		BonsVO b = TradeConvertUtils.convertBonsRtn(t);
		String fid = b.getFid();
		if(null == TradeUtils.BONS_MAP.get(fid)) {
			Map<Integer, BonsVO> bonsMap = new HashMap<Integer, BonsVO>();
			TradeUtils.BONS_MAP.put(fid, bonsMap);
		}
		TradeUtils.BONS_MAP.get(fid).put(b.getDirection(), b);
	}
	
	
	@Override
	public void initTradeApi(CThostFtdcTraderApi traderApi) {
		this.traderApi = traderApi;
	}

	@Override
	public void insertTradeReq(ReqVO t) {
		tradeMapper.insertTradeReq(t);
	}

	@Override
	public void insertTradeKC(ReqVO t) {
		tradeMapper.insertTradeKC(t);
	}

	@Override
	public void insertTradePC(ReqVO t) {
		tradeMapper.insertTradePC(t);
	}

	@Override
	public void initBons() {
		TradeUtils.BONS_MAP.clear();
		traderApi.ReqQryInvestorPosition(TradeConvertUtils.initBonsParams(CtpUser.getCurrUser()) , TradeTimeUtils.getCurrReqId());
	}
	
}
